<!--
 * @Author: your name
 * @Date: 2021-03-29 18:08:46
 * @LastEditTime: 2021-09-23 23:44:57
 * @LastEditors: Please set LastEditors
 * @Description: In User Settings Edit
 * @FilePath: \jet_mesc:\js\jinma_qms\src\components\MarkupTable.vue
-->
<template>
  <div>
    <div class="text-grey-7" v-if="_label">{{_label}}</div>
    <q-markup-table
      flat
      dense
      :bordered="!!_bordered"
      :separator="_separator || 'cell'"
    >
      <thead>
        <tr>
          <th :class="['text-center',
                       'my-th-'+col.name, col.name === 'operate' ? 'my-operate' : '']" v-for="(col, idx) in _columns" :key="idx">
            {{col.label}}
          </th>
        </tr>
      </thead>
      <tbody>
        <tr v-for="(row, idx) in rows" :key="idx">
          <td
            :class="['my-cell',
                     typeof col.class === 'function' ? col.class(row[col.field], row) : col.class || 'text-center']"
            v-for="(col, idx) in _columns"
            :key="idx"
          >
            <!-- 有这个slot，会拉慢整体的render速度，特别是做为子表使用，有很多该组件的时候，特别特别的慢，不知如何优化 -->
            <slot :name="'body-'+col.name" v-bind:props="{ col: {...col, value: columnValue(col, row)}, row }">
              {{columnValue(col, row)}}
            </slot>
            <!-- 显示新旧对比内容 -->
            <div v-if="canShowCompare(col.field)" class="compare text-bold" v-html="compareValue(row, col.field)"></div>
          </td>
        </tr>
      </tbody>
      <tfoot v-if="needFooter">
        <tr class="bg-yellow-2">
          <th
            v-for="(col, idx) in _columns.filter(v => v.footer)"
            :class="['text-center', col.footer.class || '']"
            :key="'footer_'+idx"
            :colspan="col.footer.colspan || 1"
          >
            <slot :name="'footer-'+col.name" v-bind:props="{ col }">
              {{typeof col.footer.label === 'function' ? col.footer.label(rows, masterData) : col.footer.label}}
            </slot>
          </th>
        </tr>
      </tfoot>
    </q-markup-table>
    <div class="q-field__bottom" v-if="field && field.hint">{{field.hint}}</div>
  </div>
</template>

<script>
import { defineComponent } from 'vue';
export default defineComponent({
  props: {
    field: {
      type: Object,
      default: () => {}
    },
    label: {
      type: String,
      default: ''
    },
    bordered: {
      type: Boolean,
      default: false
    },
    separator: {
      type: String,
      default: 'cell'
    },
    columns: {
      type: Array,
      default: () => []
    },
    value: {
      type: [String, Array],
      default: ''
    },
    compare: {
      type: Object,
      default: () => {}
    },
    masterData: { // 主表数据，给footer的label为函数时使用
      type: [Object, Array],
      default: () => {}
    }
  },
  mounted () {
    this.adjustFooter();
    this.adjustColumnValue();
  },
  methods: {
    columnValue (col, row) {
      if (row._colsValue && row._colsValue[col.field] !== undefined) {
        return row._colsValue[col.field];
      } else {
        return typeof col.format === 'function' ? col.format(row[col.field], row) : row[col.field] || '';
      }
    },
    adjustColumnValue () {
      for (const row of this.rows) {
        const colsValue = {};
        for (const col of this._columns) {
          colsValue[col.field] = typeof col.format === 'function' ? col.format(row[col.field], row) : row[col.field] || '';
        }
        row._colsValue = colsValue;
      }
    },
    canShowCompare (field) {
      /*
        compare的值
        compare: {
          label, // 标题
          keyField, // 定位数据的字段
          value, // 做对比数据集
          fields, // 可做对比的字段 不定义，表示全都对比，若定义，array型，例如：['field1', { oldField: newField}, ...]，各项数据，若为字符，则为该字段，若为键值对，key表示定义的字段名，value表示取数据的字段名，value还能为function
          always // true-有数据就显示 false-值不同，再显示
        } */
      return this._compare && this._compare.keyField &&
        (!this._compare.fields || this._compare.fields.map(v => typeof v === 'string' ? v : Object.keys(v)[0]).includes(field)) &&
        this._compare.value && this._compare.value.length > 0;
    },
    compareValue (row, field) { // 新老值对比
      let compareResult = '';

      const key = String(row[this._compare.keyField]);
      const compareRow = this.compareObj[key];

      let dataField = field;
      if (this._compare.fields) {
        const idx = this._compare.fields.findIndex(v => (typeof v === 'string' ? v : Object.keys(v)[0]) === dataField);
        const defineField = this._compare.fields[idx];
        if (typeof defineField === 'object') {
          dataField = defineField[field];
        }
      }
      let curValue, comValue;
      if (typeof dataField === 'function') {
        curValue = dataField(row);
        comValue = compareRow ? dataField(compareRow) : '';
      } else {
        curValue = row[dataField];
        comValue = compareRow ? compareRow[dataField] : '';
      }

      if (this._compare.always || compareRow && curValue != comValue) {
        compareResult = `<div class="text-white bg-yellow-10">${this._compare.label ? this._compare.label + '：' : ''}${comValue}</div>`;
      } else if (compareRow === undefined) {
        compareResult = '<div class="bg-red-8 text-white">新增内容</div>';
      }
      return compareResult;
    },
    adjustFooter () {
      if (this._columns.filter(v => v.footer).length > 0) {
        let lastCol = {};
        // 判断第一列有没有footer
        if (!this._columns[0].footer) {
          this._columns[0].footer = { label: '', colspan: 1 };
        }
        for (const col of this._columns) {
          if (col.footer) {
            col.footer.colspan = 1;
            lastCol = col;
          } else {
            lastCol.footer.colspan += 1;
          }
        }
      }
    }
  },
  computed: {
    rows () {
      if (typeof this._value === 'string') {
        return this._value ? JSON.parse(this._value) : [];
      } else {
        return this._value;
      }
    },
    _label () {
      return this.field ? this.field.label : this.label;
    },
    _bordered () {
      return this.field ? this.field.bordered : this.bordered;
    },
    _separator () {
      return this.field ? this.field.separator : this.separator;
    },
    _columns () {
      const field = this.field ? this.field.columns : this.columns;
      return field.filter(v => v.visible !== false);
    },
    _value () {
      return this.field ? this.field.value : this.value;
    },
    _compare () {
      return this.field ? this._compare : this.compare;
    },
    compareObj () { // 把对比的数据转成对象
      if (this._compare && this._compare.value && this._compare.value.length > 0 && this._compare.keyField) {
        const compareValue = typeof this._compare.value === 'string' ? JSON.parse(this._compare.value) : this._compare.value;
        const obj = {};
        for (const row of compareValue) {
          const key = String(row[this._compare.keyField]);
          obj[key] = row;
        }
        return obj
      } else {
        return {};
      }
    },
    needFooter () {
      return this._columns.filter(col => col.footer).length > 0;
    }
  },
  watch: {
    _columns () {
      this.adjustFooter();
    },
    _value () {
      this.adjustColumnValue();
    }
  }
});
</script>

<style>
td.my-cell {
  word-break: break-all;
 /*  max-width: 200px; */
}

th.my-operate{
  width: 130px;
}

.compare {
  margin-top: 8px;
  font-size: 12px;
}
</style>
